package functions;

import types.*;

import java.util.Random;

public class GenerateProgram {
	public GenerateProgram() {
	}
	// function to generate program based on the entered parameters

	public static Block[] getGenerateProgram(String p1, String p2, String p3,
			String p4, String p5, String p6) {
		int prog_size_line = Integer.parseInt(p1);
		int if_num = Integer.parseInt(p2);
		int if_else_num = Integer.parseInt(p3);
		int for_num = Integer.parseInt(p4);
		int while_num = Integer.parseInt(p5);
		int func_num = Integer.parseInt(p6);
		int index = 0; // for blocks number
		int regular_line_final = 0;
		int blocks_lines = 0;
		int regular_block_line = 0;

		int blocks_num = if_num + if_else_num + for_num + while_num + func_num;
		if (blocks_num == 0) {
			// array of regular blocks only
			Block[] ProgBlocks = new Block[1];
			ProgBlocks[0] = new Block(prog_size_line, "regular");
			return ProgBlocks;

		}

		// Blocks Array of block
		Block[] Blocks = new Block[blocks_num];
		// ALL Program Blocks
		Block[] ProgBlocks = new Block[2 * blocks_num + 1];

		Double regularCodeMean = (double) (prog_size_line / blocks_num);
		Double regularCodeVar = regularCodeMean / 10;
		int regularCodeLine;

		RandomGaussian RG_reg = new RandomGaussian(regularCodeMean,
				regularCodeVar); // regular code percentage of the program
		regularCodeLine = (int) ((prog_size_line * RG_reg.getRes()) / 100); // num
																			// of
																			// regular
																			// lines

		Double blockSizeMean = (double) ((prog_size_line - regularCodeLine) / blocks_num);

		// if
		if (if_num > 0) {
			for (int i = 0; i < if_num; i++, index++) {
				RandomGaussian RG = new RandomGaussian(blockSizeMean,
						blockSizeMean * 0.2); // regular code percentage of the
												// program
				Blocks[index] = new Block(RG.getRes().intValue(), "if");
			}
		}
		// if else
		if (if_else_num > 0) {
			for (int i = 0; i < if_else_num; i++, index++) {
				RandomGaussian RG = new RandomGaussian(blockSizeMean,
						blockSizeMean * 0.5); // regular code percentage of the
												// program
				Blocks[index] = new Block(RG.getRes().intValue(), "if_else");
			}
		}
		// for
		if (for_num > 0) {
			for (int i = 0; i < for_num; i++, index++) {
				RandomGaussian RG = new RandomGaussian(blockSizeMean,
						blockSizeMean * 0.4); // regular code percentage of the
												// program
				Blocks[index] = new Block(RG.getRes().intValue(), "for");
			}
		}
		// while
		if (while_num > 0) {
			for (int i = 0; i < while_num; i++, index++) {
				RandomGaussian RG = new RandomGaussian(blockSizeMean,
						blockSizeMean * 0.4); // regular code percentage of the
												// program
				Blocks[index] = new Block(RG.getRes().intValue(), "while");
			}
		}
		// func
		if (func_num > 0) {
			for (int i = 0; i < func_num; i++, index++) {
				RandomGaussian RG = new RandomGaussian(blockSizeMean,
						blockSizeMean * 0.7); // regular code percentage of the
												// program
				Blocks[index] = new Block(RG.getRes().intValue(), "func");
			}
		}
		//

		for (int i = 0; i < index; i++)
			blocks_lines += Blocks[i].getLine();

		// get the regular block size
		regular_line_final = prog_size_line - blocks_lines;
		regular_block_line = (int) (regular_line_final / (index + 1));

		// shuffle to Blocks array
		Random random = new Random();
		random.nextInt();
		for (int i = 0; i < index; i++) {
			int change = i + random.nextInt(index - i);
			swap(Blocks, i, change);
		}

		// construct the array of special and regular blocks
		for (int i = 0, j = 0; i < (2 * blocks_num + 1); i++) {
			if (i % 2 == 0)
				ProgBlocks[i] = new Block(regular_block_line, "regular");
			else {
				ProgBlocks[i] = new Block();
				ProgBlocks[i].copyBlock(Blocks[j]);
				j++;
			}
		}
		return ProgBlocks;

	}

	private static void swap(Block[] a, int i, int change) {
		Block helper = a[i];
		a[i] = a[change];
		a[change] = helper;
	}

}
